package com.rrd.hive.udf.excel;

import org.apache.hadoop.hive.ql.exec.UDF;

/**
 * EXCEL PMT函数
 * 实现PMT函数，需要传入4-6个参数：
 * 参数1 r：为各期利率
 * 参数2 per：用于计算其本金数额的期数，必须介于 1 到 nper 之间
 * 参数3 nper：为总投资期，即该项投资的付款期总数。
 * 参数4 pv：贷款金额,现值，或一系列未来付款的当前值的累积和，也称为本金
 * 参数5 fv：为未来值，或在最后一次付款后希望得到的现金余额，如果省略 fv，则假设其值为零，也就是一笔贷款的未来值为零。
 * 参数6 type：付款时：期初为1；期末为0
 * @author liubaoxin
 * @date 2020年2月20日
 */
public class ExcelPPMTUDF extends UDF {

	public Double evaluate(double r, int per, int nper, double pv) {
		return evaluate(r,per,nper,pv,0);
	}
	public Double evaluate(double r, int per, int nper, double pv, double fv) {
		return evaluate(r,per,nper,pv,fv,0);
	}
	public Double evaluate(double r, int per, int nper, double pv, double fv, int type) {
		 return pmt(r, nper, pv, fv, type) - ipmt(r, per, nper, pv, fv, type);
	}
	
	static public double pmt(double r, int nper, double pv, double fv, int type) {
         return -r * (pv * Math.pow(1 + r, nper) + fv) / ((1 + r*type) * (Math.pow(1 + r, nper) - 1));
 	}
	 static public double ipmt(double r, int per, int nper, double pv, double fv, int type) {
		    double ipmt = fv(r, per - 1, pmt(r, nper, pv, fv, type), pv, type) * r;
		    if (type==1) ipmt /= (1 + r);
		    return ipmt;
	}
	 static public double fv(double r, int nper, double pmt, double pv, int type) {
         return -(pv * Math.pow(1 + r, nper) + pmt * (1+r*type) * (Math.pow(1 + r, nper) - 1) / r);
 	}
	public static void main(String[] args) {
		ExcelPPMTUDF pmt = new ExcelPPMTUDF();
		  System.out.println(pmt.evaluate(0.07/12,24, 30*12, 165000d, 0, 0));
	}
}
